#include <os_common_api.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <bt_manager.h>
//#include "btmusic.h"
#include "uart_control.h"
#include "app_defines.h"
#include "input_manager.h"
#include "app_manager.h"
#include "app_switch.h"
#include "volume_manager.h"
#include "audio_system.h"
#include "sys_manager.h"





static struct uart_buf_info uart_buf[UART_BUF_QUEUED];
struct uart_data_format send_cache;			/* 串口TX临时缓存区 */

u8_t rx_data[2][UART_MTU];
u8_t rx_index[2]={0};

u8_t alarm_ringing_enable;
u8_t mcu_is_ready=0;

static K_FIFO_DEFINE(cmds_queue_uart1);
static K_FIFO_DEFINE(avail_queue_uart1);
static os_delayed_work uart1_control_run_delaywork;



/**
 * uart1 tx send
 *
 * @param
 *  p_data
 */
void uart1_send_to_apt(     u8_t *p_data,u8_t writen_len)
{
    //SYS_LOG_INF(" reply3 %d\n", writen_len);
    if(writen_len > UART_MTU){
        SYS_LOG_ERR("uart1: TX data_len err.");
        return;
    }
    if(writen_len ==0){
        SYS_LOG_ERR("uart1: TX cmd_len err.");
        return;
    }
	printk("TX:\n");
    print_buffer(p_data, 1, writen_len, 16, 0);
    uart_pipe_send((u8_t *)p_data, writen_len);
}

void get_cur_status(void)
{
	if(strcmp(app_manager_get_current_app(), APP_ID_BTMUSIC)==0)
	{
		u16_t bt_state;
		bt_state=bt_manager_get_status()&BT_STATUS_PLAYING;
	}
	else if(strcmp(app_manager_get_current_app(), APP_ID_LINEIN)==0)
	{
		
	}
}
//len+cmd+param
u8_t get_checksum(u8_t *data,u8_t length)
{
	u16_t checksum=0,i=0;
	for(i=0;i<length;i++)
	{
		checksum+=data[i];
	}
	checksum=0xFF-(checksum&0xFF);
	printf("cur checksum:0x%x\n",checksum);
	return checksum;
}
#define HEAD_OFFSET 0
#define LEN_OFFSET 1
#define CMD_OFFSET 2
#define PARAM_OFFSET 3
#define CHECKSUM_OFFSET 4
#define END_OFFSET 5

void send_msg_to_apt(u8_t cmd)
{
	//struct uart_data_format tx_msg;
	u8_t send_buf[40],send_length=0;
	memset(send_buf,0x0,40);
	send_buf[HEAD_OFFSET]=MAGIC_HEAD;		
	send_buf[CMD_OFFSET]=cmd;	
	switch(cmd)
	{
		case CMD_STATUS_QUERY:
			send_buf[3]=system_volume_get(AUDIO_STREAM_MUSIC)&0x1F;
			if(strcmp(app_manager_get_current_app(), APP_ID_BTMUSIC)==0)
			{
				u16_t bt_state=bt_manager_get_status();
				if((bt_state&BT_STATUS_CONNECTED)!=BT_STATUS_CONNECTED)
				{
					
				}
				else if((bt_state&BT_STATUS_PLAYING)==BT_STATUS_PLAYING)
				{
					send_buf[PARAM_OFFSET]|=0xC0;
				}
				else
				{
					send_buf[PARAM_OFFSET]|=0x80;
				}
			}
			else if(strcmp(app_manager_get_current_app(), APP_ID_LINEIN)==0)
			{
				send_buf[PARAM_OFFSET]|=0x60;
			}
			else
			{
				send_buf[PARAM_OFFSET]|=0x80;
			}	
			send_buf[LEN_OFFSET]=4;
			send_buf[CHECKSUM_OFFSET]=get_checksum(&send_buf[LEN_OFFSET],3);
			send_buf[END_OFFSET]=MAGIC_END;
			send_length=6;
			break;
		case CMD_GET_DEVICE_NAME:
			if(strcmp(app_manager_get_current_app(), APP_ID_BTMUSIC)!=0)
			{
				return;
			}
			else 
			{
				u16_t bt_state=bt_manager_get_status();
				if((bt_state&BT_STATUS_CONNECTED)!=BT_STATUS_CONNECTED)
				{
					send_buf[PARAM_OFFSET]=0;
					send_buf[LEN_OFFSET]=4;
					send_buf[CHECKSUM_OFFSET]=get_checksum(&send_buf[LEN_OFFSET],3);
					send_buf[END_OFFSET]=MAGIC_END;
					send_length=6;
				}
				else
				{
					u8_t name_len=0;
					bt_manager_get_device_name(&send_buf[3]);					
					name_len=strlen(&send_buf[3])-1;
					printf("name len:%d\n",name_len);
					print_buffer(&send_buf[3],1,name_len,32,0);
					send_buf[LEN_OFFSET]=name_len+3;
					send_buf[name_len+PARAM_OFFSET]=get_checksum(&send_buf[LEN_OFFSET],name_len+2);
					send_buf[name_len+CHECKSUM_OFFSET]=MAGIC_END;
					send_length=5+name_len;
					if(send_length>16)
					{
						send_length=16;
					}
				}
			}
			break;
		default:
			return;
	}
	uart1_send_to_apt(send_buf,send_length);
}
void report_msg_to_bt(uint8_t msg_cmd,void *buf)
{
	struct app_msg  msg = {0};
	msg.type = MSG_BT_EVENT;
	msg.cmd = msg_cmd;
	msg.ptr =buf;
	send_async_msg(APP_ID_BTMUSIC, &msg);
}
void report_msg_to_main(uint8_t msg_cmd,void *buf)
{
	struct app_msg  msg = {0};
	msg.type = MSG_SYS_EVENT;
	msg.cmd = msg_cmd;
	msg.ptr =buf;
	send_async_msg(APP_ID_MAIN, &msg);
}

/**
 * uart1 rx recv dispatch
 *
 * @param
 *  p_data
 */
u8_t g_bat_status = 1;
u8_t g_mcu_reset = 0;
u8_t data_buf[32];
void uart1_dispatch(     u8_t *p_data)
{
	struct uart_data_format *p_reply = (void *)p_data;
	u16_t writen_len = p_reply->data_len;
    u8_t cmd = p_reply->cmd;

    //todo send event/msg base rx info
#ifdef UART_DEBUG
    SYS_LOG_INF(" magic %x\n", p_reply->magic);

	//write output
    p_reply->magic = 0x3E;  //应答flag ">"

    SYS_LOG_INF(" reply %d,%x\n", writen_len, p_data[writen_len]);
    //追加/替换最后一个字符为"@"来做ack
    if(writen_len < UART_MTU)
    {
        p_data[writen_len] = 0x40;
        SYS_LOG_INF(" data %x,%x\n", p_data[writen_len-1], p_data[writen_len]);
        uart_pipe_send((u8_t *)p_reply, writen_len+1);
    }
    else
    {
        p_data[UART_MTU-1] = 0x40;
        uart_pipe_send((u8_t *)p_reply, UART_MTU);
    }
    print_buffer(p_data, 1, writen_len+1, 16, 0);
#else
	if(p_reply->magic!=MAGIC_HEAD)
	{
		SYS_LOG_INF(" magic err:%x\n",p_reply->magic);
		return ;
	}
    //uart_pipe_send((u8_t *)p_reply, writen_len);
    if(writen_len != 0)
    {
    	u8_t msg_cmd=0;
        SYS_LOG_INF("cmd_type:0x%x\n", cmd);
        switch(cmd)
        {
        	case CMD_BT_PLAY:
				msg_cmd=MSG_BT_PLAY;
				break;
            case CMD_BT_PAUSE:
				msg_cmd=MSG_BT_PAUSE;
				break;
			case CMD_BT_VOL_ADD:
				msg_cmd=MSG_BT_VOL_ADD;
				break;
			case CMD_BT_VOL_SUB:
				msg_cmd=MSG_BT_VOL_SUB;
				break;
			case CMD_BT_MUSIC_PREV:
				msg_cmd=MSG_BT_MUSIC_PREV;
				break;
			case CMD_BT_MUSIC_NEXT:
				msg_cmd=MSG_BT_MUSIC_NEXT;
				break;
			case CMD_SWITCH_APP:
				data_buf[0]=p_reply->param;
				if(data_buf[0]==0&&(strcmp(app_manager_get_current_app(), APP_ID_LINEIN)==0))
				{
					app_switch(APP_ID_BTMUSIC, APP_SWITCH_CURR, true);
				}
				else if(data_buf[0]==1&&(strcmp(app_manager_get_current_app(), APP_ID_BTMUSIC)==0))
				{
					app_switch(APP_ID_LINEIN, APP_SWITCH_CURR, true);
				}
				//msg_cmd=MSG_SWITCH_APP;
				//report_msg_to_main(msg_cmd,data_buf);
				return;
			case CMD_BT_DISCONNECT:
				msg_cmd=MSG_BT_DISCONNECT;
				break;
			case CMD_SET_VOL:
				data_buf[0]=p_reply->param;
				msg_cmd=MSG_SET_VOL;
				break;
			case CMD_STATUS_QUERY:
				send_msg_to_apt(cmd);
				return;
				//msg_cmd=MSG_STATUS_QUERY;
				//break;
			case CMD_GET_DEVICE_NAME:
				send_msg_to_apt(cmd);
				return;
				//msg_cmd=MSG_GET_DEVICE_NAME;
				//break;
			case CMD_SET_DISCOVERABLE:
				data_buf[0]=p_reply->bt_name[0];
				msg_cmd=MSG_SET_DISCOVERABLE;
				break;
			case CMD_SET_CONNNECTABLE:
				data_buf[0]=p_reply->bt_name[0];
				msg_cmd=MSG_SET_CONNNECTABLE;
				break;
			case CMD_CLEAR_PAIR_INFO:
				msg_cmd=MSG_CLEAR_PAIR_INFO;
				break;
			case CMD_POWER_OFF:
				msg_cmd=MSG_BT_POWER_OFF;
				break;
			case CMD_RESTART:
				//msg_cmd=MSG_RESTART;
				system_power_off_reboot();
				break;
			case CMD_MODIFY_BT_NAME:
				memcpy(data_buf,p_reply->bt_name,writen_len-3);
				bt_modify_bt_name(data_buf);
				
				//data_buf[0]=p_reply->param;
				//msg_cmd=MSG_MODIFY_BT_NAME;
				break;
			case CMD_ANSWER_THE_PHONE:
				msg_cmd=MSG_ANSWER_THE_PHONE;
				break;
			case CMD_REJECT_A_CALL:
				msg_cmd=MSG_REJECT_A_CALL;
				break;
			case CMD_HANGUP_CALL:
				msg_cmd=MSG_HANGUP_CALL;
				break;
			case CMD_HANGUP_THE_SECOND_CALL:
				msg_cmd=MSG_HANGUP_THE_SECOND_CALL;
				break;
			case CMD_HANGUP_CUR_ANSWER_NEXT:
				msg_cmd=MSG_HANGUP_CUR_ANSWER_NEXT;
				break;
			case CMD_KEEP_CUR_ANSWSER_NEXT:
				msg_cmd=MSG_KEEP_CUR_ANSWSER_NEXT;
				break;
			case CMD_SWITCH_TO_PHONE:
				msg_cmd=MSG_SWITCH_TO_PHONE;
				break;
			case CMD_DIAL_LAST_NUM:
				msg_cmd=MSG_DIAL_LAST_NUM;
				break;
			case CMD_RECONNECT_LAST_DEVICE:	
				msg_cmd=MSG_RECONNECT_LAST_DEVICE;
				break;
            default:
                SYS_LOG_INF("uart cmd error.\n");
                return;
        }
		report_msg_to_bt(msg_cmd,data_buf);
    }

#endif	
	return;
}
/**
 * exec in system workqueue
 */
static void uart1_cmd_handle(os_work *work)
{
	struct uart_buf_info *cmd_buf = NULL;
	#if 1
	u8_t i;
	for(i=0;i<UART_BUF_QUEUED;i++)
	{
		cmd_buf = k_fifo_get(&cmds_queue_uart1, K_NO_WAIT);

	    //SYS_LOG_INF(" %08x\n", (unsigned)cmd_buf);
		if (cmd_buf == NULL)
	    {
	        continue;
	    }
	    SYS_LOG_INF(" %08x\n", (unsigned)cmd_buf->data);

		//dispatch handle
	    uart1_dispatch(cmd_buf->data);
		k_fifo_put(&avail_queue_uart1, cmd_buf);
	}
	#else
	cmd_buf = k_fifo_get(&cmds_queue_uart1, K_NO_WAIT);

    //SYS_LOG_INF(" %08x\n", (unsigned)cmd_buf);
	if (cmd_buf == NULL)
    {
        SYS_LOG_ERR("uart1: cmd_buf get error 3");
		return;
    }
    //SYS_LOG_INF(" %08x\n", (unsigned)cmd_buf->data);
	//dump
	//print_buffer(cmd_buf->data, 1, cmd_buf->data_info.data_len+1, 16, 0);
	//print_buffer(cmd_buf->data, 1, cmd_buf->data_info.data_len, 16, 0);

	//dispatch handle
    uart1_dispatch(cmd_buf->data);

	k_fifo_put(&avail_queue_uart1, cmd_buf);
	#endif
}

/**
 * notice this function exec in ISR context
 */
static u8_t *uart1_recv_cb(u8_t *buf, size_t *off)
{
    struct uart_data_format *cmds_buf = (void *) buf;
    struct uart_buf_info *new_buf;
    u16_t len;
	//printk("buf addr:0x%x\n",(unsigned)buf);
	printk("RX:\n");
	print_buffer(buf, 1, *off, 16, (u32_t)*buf);
    //SYS_LOG_INF("1> %08x, %ld,%ld\n", (unsigned)buf, *off, sizeof(*cmds_buf));
    //print_buffer(buf, 1, *off, 16, 0);
    if (cmds_buf->magic != MAGIC_HEAD) {
        SYS_LOG_ERR("uart1: RX magic error 0x%x,len:%ld", cmds_buf->magic,*off);
        //if(*off >= UART_MTU)
            *off = 0;
        return buf;
    }
#if 0
    if (*off < sizeof(*cmds_buf)) {
        SYS_LOG_ERR("uart1: RX data not enough 0");
        if(*off >= UART_MTU)
            *off = 0;
		return buf;
	}
#else
    //uart control的最小长度，防止拿到错误的数据长度
    if(*off < 0x03){
        //SYS_LOG_ERR("uart1: RX data not enough 0");
        if(*off >= UART_MTU)
            *off = 0;
        return buf;
    }
#endif
    //SYS_LOG_INF("2> %08x, %d,%ld\n", (unsigned)buf, cmds_buf->data_len, *off);

    len = cmds_buf->data_len+2;

    //防止buffer长度溢出，规避死循环
    if(len > UART_MTU){
        *off = 0;
        SYS_LOG_ERR("uart1: TX data_len err %d", len);
        return buf;
    }

    //判断输入长度是否达到格式要求，未达到则重新缓存
    if (*off < len) {
        //SYS_LOG_ERR("uart1: RX data not enough 1:%ld", *off);
        if(*off <= UART_MTU)    //防止超出buffer大小
        {
            return buf;
        }
        SYS_LOG_ERR("uart1: RX buf full");
    }

	#if 1
    new_buf =  k_fifo_get(&avail_queue_uart1, K_NO_WAIT);
    if (!new_buf) {
        SYS_LOG_ERR("uart1: RX overflow 2");
        *off = 0;
        return buf;
    }
	#endif
    k_fifo_put(&cmds_queue_uart1, CONTAINER_OF(buf, struct uart_buf_info, data));
    os_delayed_work_submit(&uart1_control_run_delaywork, UART_RXTX_INTERVAL);
	
    *off = 0;
	memset(new_buf->data, 0, UART_MTU);
    return new_buf->data;
}


/*initialize uart1*/
void uart1_setting_init(void)
{
	int i;
	struct uart_buf_info *buf;

	for (i = 0; i < UART_BUF_QUEUED; i++) {
		k_fifo_put(&avail_queue_uart1, &uart_buf[i]);
	}

	buf = k_fifo_get(&avail_queue_uart1, K_NO_WAIT);
	uart_pipe_register(buf->data, UART_MTU, uart1_recv_cb);

	SYS_LOG_INF("uart1 communication init\n");
	os_delayed_work_init(&uart1_control_run_delaywork, uart1_cmd_handle);
}

